"""This pymak extension defines rules and actions for the GnuText framework to
create .po, .pot and .mo files.
"""

# Python imports
import logging
import os

# PyMak imports
import pymak
from pymak.path import to_path

MAJOR_VERSION = 1
MINOR_VERSION = 0

def init(context):
    """This method sets up into the provided PyMak context the following:

    Properties called XGETTEXT, MSGFMT and MSGINIT which are defined
    in terms of the GNUTEXT_HOME env var (which should have been
    configured by defining a thirdparty component).

    A .pot Rule which sets up a target to run the .pot.any action.

    A .pot.any Action, which invokes the xgettext tool on all its dependent targets.

    A .po Rule which sets up a target to run the .po.pot Action.

    A .po.pot Action which invokes the msginit tool.

    A .mo Rule which sets up a target with the .mo.po action.

    A .mo.po action which runs the msgfmt tool on a dependent .po file to generate the .mo file.

    An action to convert a .pot to a .po with all the messages having their case swapped. This is not bound to
    any action name, so it needs to be set explicitly using the action=gnutext.SwapCaseAction() argument
    to the target factory.
    """

    context.define_property("XGETTEXT", [ ], "$(GETTEXT_HOME)/bin/xgettext")
    context.define_property("MSGFMT", [ ], "$(GETTEXT_HOME)/bin/msgfmt")
    context.define_property("MSGINIT", [ ], "$(GETTEXT_HOME)/bin/msginit")

    context.declare_rule('.pot', DefRule(context, 
                                         target_dir="build/pot/$(allvariants)",
                                         action=".pot.any"))
    
    context.declare_rule('.po', DefRule(context, 
                                        target_dir="build/po/$(allvariants)",
                                        action=".po.pot"))


    context.declare_rule('.mo', DefRule(context,
                                        target_dir="build/mo/$(allvariants)",
                                        action=".mo.po"))
        

    context.declare_action('.pot.any', MessagesFileAction())
    context.declare_action('.po.pot', InitMessagesAction())
    context.declare_action('.mo.po', CompileMessagesAction())


def version_ok(major, minor):
    if major != MAJOR_VERSION:
        return False
    if minor > MINOR_VERSION:
        return False
    return True

class DefRule(pymak.Rule):
    def __init__(self, context, **kwargs):
        super(DefRule, self).__init__(context)
        self.default_kwargs = kwargs

    def apply_rule(self, target_name, **kwargs):
        merged_kwargs = dict(self.default_kwargs)
        merged_kwargs.update(kwargs)
        return super(DefRule, self).apply_rule(target_name, **merged_kwargs)


class MessagesFileAction(pymak.CommandAction):
    """A action class which invokes the xgettext tool from the gettext package."""
    def build_command(self, target, variant_values):
        files = ' '.join([ '"%s"' % t.path for t in target._depends_on.list_of_sub_targets(variant_values) ])
        cmd = '"$(XGETTEXT)" -o "%s" ' % target.path + files
        logging.info(cmd)
        return cmd



class InitMessagesAction(pymak.CommandAction):
    """A action class which invokes the msginit tool from the gettext package."""
    def build_command(self, target, variant_values):
        locale = getattr(target, 'locale', None)
        if not locale:
            raise pymak.PyMakException('locale attribute not set on target')
        cmd = '"$(MSGINIT)" -l %s -o "%s" -i "%s"' % (locale, target.path, target._depends_on.list_of_sub_targets(variant_values)[0].path)
        logging.info(cmd)
        return cmd

class CompileMessagesAction(pymak.CommandAction):
    """A action class which invokes the msgfmt tool from the gettext package."""
    def build_command(self, target, variant_values):
        cmd = '"$(MSGFMT)" -o "%s" "%s"' % (target.path, target._depends_on.list_of_sub_targets(variant_values)[0].path)
        logging.info(cmd)
        return cmd
        

class SwapCaseAction(pymak.Action):
    """A action class which parses a .po/.pot file and produces another .po file with all the translated strings
    replaced with inverted text. This can be useful for testing that all the visible strings in an app have
    been marked appropriately so they can be found be the xgettext tool.
    """
    def execute_action(self, target, variant_values):
        logging.warning('%s...' % target.path)
        in_f = target._depends_on.list_of_sub_targets(variant_values)[0].path.open()
        out_f = target.path.open('w')

        prev = ''
        while True:
            line = in_f.readline()
            if not line:
                break
            if line.startswith('msgid "'):
                prev = line[7:-2]
            if line.startswith('msgstr "'):
                line = 'msgstr "%s"\n' % _swapcase(prev)
            out_f.write(line)

        in_f.close()
        out_f.close()

def _swapcase(str):
    result = ''
    skip = False
    for c in str:
        if skip:
            skip = False
        elif c == '\\' or c == '%':
            skip = True
        else:
            c = c.swapcase()
        result += c
        
    return result

    
